﻿SmitearWebGL.Core.Math.MAX_NUMBER_VALUE = Number.MAX_VALUE;
SmitearWebGL.Core.Math.MIN_NUMBER_VALUE = Number.MIN_VALUE;
SmitearWebGL.Core.Math.MAX_INT_VALUE = 0x7fffffff;
SmitearWebGL.Core.Math.MIN_INT_VALUE = -2147483648;
SmitearWebGL.Core.Math.MAX_UINT_VALUE = 0xffffffff;
SmitearWebGL.Core.Math.MIN_UINT_VALUE = 0;

SmitearWebGL.Core.Math.clamp = function( x, low, high )
{
	return ( ( x < low ) ? low : ( ( x > high ) ? high : x ) );
}

SmitearWebGL.Core.Math.highestBitSet = function( x )
{
	var i = 0;
	var j = 1;
	for ( ; j <= x && i < 32; i ++ , j <<= 1 );
	return i - 1;
}

SmitearWebGL.Core.Math.lowestBitSet = function( x )
{
	var i = 0;
	var j = 1;
	for ( ; ! ( j & x ) && i < 32; i ++ , j <<= 1 );
	return i;
}

SmitearWebGL.Core.Math.isPowerOfTwo = function( value )
{
	if ( value == undefined )
	return false;
	return ( value & ( value - 1 ) ) == 0;
}

SmitearWebGL.Core.Math.nearestPowerOfTwo = function( input )
{
	return Math.pow( 2, Math.round( Math.log( input ) / Math.log( 2 ) ) );
}

SmitearWebGL.Core.Math.ceilingPowerOfTwo = function( input )
{
	return Math.pow( 2, Math.ceil( Math.log( input ) / Math.log( 2 ) ) );
}

SmitearWebGL.Core.Math.floorPowerOfTwo = function( input )
{
	return Math.pow( 2, Math.floor( Math.log( input ) / Math.log( 2 ) ) );
}

SmitearWebGL.Core.Math.modulus = function( a, b )
{
	return ( a % b );
}

SmitearWebGL.Core.Math.alignUp = function( value, alignment )
{
	var remainder = SmitearWebGL.Core.Math.modulus( value, alignment );

	if ( remainder == 0 )
	{
		return( value );
	}

	return( value + ( alignment - remainder ) );
}

SmitearWebGL.Core.Math.alignDown = function( value, alignment )
{
	var remainder = SmitearWebGL.Core.Math.modulus( value, alignment );

	if ( remainder == 0 )
	{
		return( value );
	}

	return( value - remainder );
}

SmitearWebGL.Core.Math.swap = function( a, b )
{
	var temp = a;
	a = b;
	b = temp;
}

SmitearWebGL.Core.Math.randomNumber = function( min, max, seed )
{
	function nextRandomNumber( seed, Q, A, R, M, oneOverM )
	{
		var hi = seed / Q;
		var lo = seed % Q;
		var test = A * lo - R * hi;
		if(test > 0)
		{
			seed = test;
		}
		else
		{
			seed = test + M;
		}
		return (seed * oneOverM);
	}

	function randomNumberGenerator(seed)
	{
		var A = 48271;
		var M = 2147483647;
		var Q = M / A;
		var R = M % A;
		var oneOverM = 1.0 / M;
		return nextRandomNumber( seed, Q, A, R, M, oneOverM );
	}

	return ( (max-min) * randomNumberGenerator(seed) + min );
}

SmitearWebGL.Core.Math.gaussRandomPair = function( dMean, dStdDeviation )
{
	dMean = dMean == undefined ? 0.0 : dMean;
	dStdDeviation = dStdDeviation == undefined ? 1.0 : dStdDeviation;

	var x1, x2, w, y1, y2;

	do {
		x1 = 2.0 * Math.random() - 1.0;
		x2 = 2.0 * Math.random() - 1.0;
		w = x1 * x1 + x2 * x2;
	} while ( w >= 1.0 );

	w = Math.sqrt( (-2.0 * Math.log( w ) ) / w );
	y1 = x1 * w;
	y2 = x2 * w;

	var result_a = ( dMean + y1 * dStdDeviation );
	var result_b = ( dMean + y2 * dStdDeviation );

	return [result_a, result_b];
}

SmitearWebGL.Core.Math.GaussRandom = function( dMean, dStdDeviation )
{
	dMean = dMean == undefined ? 0.0 : dMean;
	dStdDeviation = dStdDeviation == undefined ? 1.0 : dStdDeviation;

	var x1, x2, w, y1;

	if ( SmitearWebGL.Core.Math._use_precalced_result )
	{
		SmitearWebGL.Core.Math._use_precalced_result = false;
		return( dMean + SmitearWebGL.Core.Math._y2 * dStdDeviation );
	}

	do {
		x1 = 2.0 * Math.random() - 1.0;
		x2 = 2.0 * Math.random() - 1.0;
		w = x1 * x1 + x2 * x2;
	} while ( w >= 1.0 );

	w = Math.sqrt( (-2.0 * Math.log( w ) ) / w );
	y1 = x1 * w;
	SmitearWebGL.Core.Math._y2 = x2 * w;

	SmitearWebGL.Core.Math._use_precalced_result = true;

	return( dMean + y1 * dStdDeviation );
}

SmitearWebGL.Core.Math._use_precalced_result = false;
SmitearWebGL.Core.Math._y2 = 0.0;

SmitearWebGL.Core.Math.toDEGREES = 180.0 / Math.PI;
SmitearWebGL.Core.Math.toRADIANS = Math.PI / 180.0;

SmitearWebGL.Core.Math.FLOAT_PRECISION					= 3.4e-8;
SmitearWebGL.Core.Math.PI								= Math.PI;
SmitearWebGL.Core.Math.TWO_PI							= 2.0*Math.PI;
SmitearWebGL.Core.Math.HALF_PI							= Math.PI/2.0;
SmitearWebGL.Core.Math.QUARTER_PI						= Math.PI/4.0;
SmitearWebGL.Core.Math.EIGHTH_PI						= Math.PI/8.0;
SmitearWebGL.Core.Math.PI_SQUARED						= 9.86960440108935861883449099987615113531369940724079;
SmitearWebGL.Core.Math.PI_INVERSE						= 0.31830988618379067153776752674502872406891929148091;
SmitearWebGL.Core.Math.PI_OVER_180						= Math.PI/180;
SmitearWebGL.Core.Math.PI_DIV_180						= 180/Math.PI;
SmitearWebGL.Core.Math.NATURAL_LOGARITHM_BASE			= 2.71828182845904523536028747135266249775724709369996;
SmitearWebGL.Core.Math.EULERS_CONSTANT					= 0.57721566490153286060651;
SmitearWebGL.Core.Math.SQUARE_ROOT_2					= 1.41421356237309504880168872420969807856967187537695;
SmitearWebGL.Core.Math.INVERSE_ROOT_2					= 0.707106781186547524400844362105198;
SmitearWebGL.Core.Math.SQUARE_ROOT_3					= 1.73205080756887729352744634150587236694280525381038;
SmitearWebGL.Core.Math.SQUARE_ROOT_5					= 2.23606797749978969640917366873127623544061835961153;
SmitearWebGL.Core.Math.SQUARE_ROOT_10					= 3.16227766016837933199889354443271853371955513932522;
SmitearWebGL.Core.Math.CUBE_ROOT_2						= 1.25992104989487316476721060727822835057025146470151;
SmitearWebGL.Core.Math.CUBE_ROOT_3						= 1.44224957030740838232163831078010958839186925349935;
SmitearWebGL.Core.Math.FOURTH_ROOT_2					= 1.18920711500272106671749997056047591529297209246382;
SmitearWebGL.Core.Math.NATURAL_LOG_2					= 0.69314718055994530941723212145817656807550013436026;
SmitearWebGL.Core.Math.NATURAL_LOG_3					= 1.09861228866810969139524523692252570464749055782275;
SmitearWebGL.Core.Math.NATURAL_LOG_10					= 2.30258509299404568401799145468436420760110148862877;
SmitearWebGL.Core.Math.NATURAL_LOG_PI					= 1.14472988584940017414342735135305871164729481291531;
SmitearWebGL.Core.Math.BASE_TEN_LOG_PI					= 0.49714987269413385435126828829089887365167832438044;
SmitearWebGL.Core.Math.NATURAL_LOGARITHM_BASE_INVERSE	= 0.36787944117144232159552377016146086744581113103177;
SmitearWebGL.Core.Math.NATURAL_LOGARITHM_BASE_SQUARED	= 7.38905609893065022723042746057500781318031557055185;
SmitearWebGL.Core.Math.GOLDEN_RATIO						= (SmitearWebGL.Core.Math.SQUARE_ROOT_5 + 1.0) / 2.0;
SmitearWebGL.Core.Math.GRAVITY_CONSTANT					= 9.81;